/*!
 * \file TraderMocker.h
 * \project WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 模拟交易接口实现
 * 
 * \details 模拟交易接口适配器，用于模拟真实交易环境
 *          提供完整的交易功能模拟，支持订单撮合、持仓管理等
 *          采用异步处理机制，支持多线程安全操作
 */
#pragma once
#include <atomic>

#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/asio/io_context.hpp>

#include "../Includes/FasterDefs.h"
#include "../Includes/ITraderApi.h"
#include "../Share/StdUtils.hpp"
#include "../Includes/WTSCollection.hpp"

NS_WTP_BEGIN
	class WTSTickData;
NS_WTP_END

USING_NS_WTP;

/*!
 * \class TraderMocker
 * \brief 模拟交易接口实现类
 * 
 * \details 模拟交易接口适配器，继承自ITraderApi
 *          实现WonderTrader统一交易接口，提供完整的交易模拟功能
 *          
 *          主要功能：
 *          - 模拟交易连接管理：模拟真实交易环境的连接状态
 *          - 模拟用户认证登录：模拟用户登录验证流程
 *          - 模拟订单管理：支持订单提交、撤单、改单等操作
 *          - 模拟持仓管理：支持持仓查询、持仓更新、持仓冻结
 *          - 模拟资金管理：支持资金查询、资金计算、保证金管理
 *          - 模拟成交撮合：基于实时行情进行订单撮合
 *          - 数据持久化：支持持仓数据的保存和加载
 *          - 实时行情接收：通过UDP接收实时行情数据
 *          - 异步处理：支持多线程异步处理，避免阻塞主线程
 *          
 *          模拟特色功能：
 *          - 支持自定义撮合规则和撮合频率
 *          - 支持最大最小成交量限制
 *          - 支持新价格模式和固定价格模式
 *          - 支持持仓数据的文件存储
 *          - 支持UDP广播行情接收
 *          - 支持多品种同时模拟交易
 *          
 * \note 主要用于策略回测和模拟交易测试
 * \warning 仅用于模拟环境，不能用于实盘交易
 * \see ITraderApi
 */
class TraderMocker : public ITraderApi
{
public:
	TraderMocker();
	~TraderMocker();

private:
	/*!
	 * \brief 执行一次撮合
	 * \return 撮合成功的订单数量
	 * 
	 * \details 根据当前行情对待成交订单进行撮合
	 *          模拟真实交易所的撮合机制
	 */
	int32_t		match_once();

	/*!
	 * \brief 生成成交ID
	 * \return 唯一的成交ID
	 * 
	 * \details 生成自增的成交标识，确保唯一性
	 */
	uint32_t	makeTradeID();
	
	/*!
	 * \brief 生成订单ID
	 * \return 唯一的订单ID
	 * 
	 * \details 生成自增的订单标识，确保唯一性
	 */
	uint32_t	makeOrderID();

	/*!
	 * \brief 加载持仓数据
	 * 
	 * \details 从文件中加载历史持仓数据
	 *          支持模拟交易的持续性
	 */
	void		load_positions();
	
	/*!
	 * \brief 保存持仓数据
	 * 
	 * \details 将当前持仓数据保存到文件
	 *          确保数据持久化
	 */
	void		save_positions();

private:
	// 线程管理
	StdThreadPtr	_thrd_match;		///< 撮合线程
	bool			_terminated;		///< 终止标志

	StdUniqueMutex		_mutex_api;		///< API互斥锁

	// ID生成器
	std::atomic<uint32_t>	_auto_trade_id;		///< 自动成交ID生成器
	std::atomic<uint32_t>	_auto_order_id;		///< 自动订单ID生成器
	std::atomic<uint32_t>	_auto_entrust_id;	///< 自动委托ID生成器

	// 核心对象
	ITraderSpi* _listener;			///< 交易事件监听器
	IBaseDataMgr*		_bd_mgr;	///< 基础数据管理器

	StdThreadPtr		_thrd_worker;	///< 工作线程

	// 配置参数
	uint32_t		_millisecs;		///< 撮合间隔毫秒数
	uint32_t		_mocker_id;		///< 模拟器ID
	bool			_use_newpx;		///< 是否使用新价格模式
	double			_max_qty;		///< 最大成交量
	double			_min_qty;		///< 最小成交量

	// 数据缓存
	WTSArray*		_orders;		///< 订单数组
	WTSArray*		_trades;		///< 成交数组
	typedef WTSHashMap<std::string> TickCache;
	TickCache*		_ticks;			///< 行情缓存

	typedef WTSHashMap<std::string> OrderCache;
	OrderCache*			_awaits;	///< 待撮合订单缓存
	StdUniqueMutex	_mtx_awaits;	///< 待撮合订单互斥锁

	faster_hashset<std::string>	_codes;	///< 合约代码集合

	// 时间管理
	uint64_t		_max_tick_time;		///< 最大行情时间
	uint64_t		_last_match_time;	///< 上次撮合时间

	/*!
	 * \struct PosUnit
	 * \brief 持仓单元结构
	 * 
	 * \details 记录单个方向的持仓信息
	 */
	typedef struct _PosUnit
	{
		double	_volume;	///< 持仓量
		double	_frozen;	///< 冻结量
	} PosUnit;

	/*!
	 * \struct PosItem
	 * \brief 持仓项目结构
	 * 
	 * \details 记录单个合约的完整持仓信息
	 */
	typedef struct _PosItem
	{
		char	_exchg[MAX_INSTRUMENT_LENGTH];	///< 交易所代码
		char	_code[MAX_INSTRUMENT_LENGTH];	///< 合约代码

		PosUnit		_long;		///< 多头持仓
		PosUnit		_short;		///< 空头持仓

		_PosItem()
		{
			memset(this, 0, sizeof(_PosItem));
		}
	} PosItem;

	faster_hashmap<std::string, PosItem> _positions;	///< 持仓映射表
	std::string		_pos_file;							///< 持仓文件路径

private:
	// UDP行情接收
	int			_udp_port;		///< UDP端口号

	boost::asio::ip::udp::endpoint	_broad_ep;		///< 广播端点
	boost::asio::io_context			_io_service;	///< IO服务

	boost::asio::ip::udp::socket*	_b_socket;		///< UDP套接字

	boost::array<char, 1024> _b_buffer;				///< 接收缓冲区

	/*!
	 * \brief 处理UDP数据接收
	 * \param e 错误码
	 * \param bytes_transferred 传输字节数
	 * \param isBroad 是否广播数据
	 * 
	 * \details 处理UDP行情数据的异步接收
	 */
	void	handle_read(const boost::system::error_code& e, std::size_t bytes_transferred, bool isBroad);

	/*!
	 * \brief 解析接收缓冲区
	 * \param length 数据长度
	 * \param isBroad 是否广播数据
	 * 
	 * \details 解析UDP接收到的行情数据
	 */
	void	extract_buffer(uint32_t length, bool isBroad);

	/*!
	 * \brief 重连UDP
	 * 
	 * \details 重新建立UDP连接，用于异常恢复
	 */
	void	reconn_udp();

//////////////////////////////////////////////////////////////////////////
//ITraderApi接口实现
public:
	/*!
	 * \brief 初始化模拟交易接口
	 * \param params 初始化参数
	 * \return 成功返回true，失败返回false
	 * 
	 * \details 初始化模拟交易接口，设置模拟参数
	 *          必需参数：
	 *          - id: 模拟器ID
	 *          - millisecs: 撮合间隔毫秒数
	 *          
	 *          可选参数：
	 *          - use_newpx: 是否使用新价格模式
	 *          - max_qty: 最大成交量
	 *          - min_qty: 最小成交量
	 *          - udp_port: UDP行情端口
	 *          - pos_file: 持仓文件路径
	 */
	virtual bool init(WTSVariant *params) override;

	/*!
	 * \brief 释放模拟交易接口资源
	 * 
	 * \details 清理所有资源，停止撮合线程
	 *          保存持仓数据，释放内存
	 */
	virtual void release() override;

	/*!
	 * \brief 注册交易事件监听器
	 * \param listener 事件监听器指针
	 * 
	 * \details 设置交易事件的回调处理器
	 *          用于接收交易相关的事件通知
	 */
	virtual void registerSpi(ITraderSpi *listener) override;

	/*!
	 * \brief 连接到模拟交易服务
	 * 
	 * \details 启动模拟交易服务，开始撮合线程
	 *          建立UDP行情接收连接
	 */
	virtual void connect() override;

	/*!
	 * \brief 断开模拟交易服务连接
	 * 
	 * \details 停止撮合线程，关闭UDP连接
	 *          保存持仓数据
	 */
	virtual void disconnect() override;

	/*!
	 * \brief 检查连接状态
	 * \return 已连接返回true，未连接返回false
	 * 
	 * \details 检查模拟交易服务的连接状态
	 */
	virtual bool isConnected() override;

	/*!
	 * \brief 生成委托单号
	 * \param buffer 输出缓冲区
	 * \param length 缓冲区长度
	 * \return 成功返回true，失败返回false
	 * 
	 * \details 生成唯一的委托单号标识
	 *          格式：模拟器ID_委托ID
	 */
	virtual bool makeEntrustID(char* buffer, int length) override;

	/*!
	 * \brief 模拟用户登录
	 * \param user 用户名
	 * \param pass 密码
	 * \param productInfo 产品信息
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 模拟用户登录流程，总是返回成功
	 */
	virtual int login(const char* user, const char* pass, const char* productInfo) override;

	/*!
	 * \brief 模拟用户登出
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 模拟用户登出流程，总是返回成功
	 */
	virtual int logout() override;

	/*!
	 * \brief 提交模拟订单
	 * \param eutrust 委托单对象
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 提交模拟交易订单，加入撮合队列
	 *          支持限价单、市价单等多种订单类型
	 */
	virtual int orderInsert(WTSEntrust* eutrust) override;

	/*!
	 * \brief 模拟订单操作（撤单）
	 * \param action 订单操作对象
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 对已提交的模拟订单进行撤单操作
	 */
	virtual int orderAction(WTSEntrustAction* action) override;

	/*!
	 * \brief 查询模拟资金账户
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 查询模拟资金账户信息
	 *          返回模拟的资金数据
	 */
	virtual int queryAccount() override;

	/*!
	 * \brief 查询模拟持仓信息
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 查询模拟持仓信息
	 *          返回当前所有持仓数据
	 */
	virtual int queryPositions() override;

	/*!
	 * \brief 查询模拟订单信息
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 查询当日所有模拟订单信息
	 *          包括已成交、部分成交、未成交订单
	 */
	virtual int queryOrders() override;

	/*!
	 * \brief 查询模拟成交信息
	 * \return 成功返回0，失败返回错误码
	 * 
	 * \details 查询当日所有模拟成交信息
	 *          包括成交价格、成交数量、成交时间等
	 */
	virtual int queryTrades() override;
};
